package com.sheng.leetcode.year2025.month09.day14;

import org.junit.Test;

import java.util.*;

/**
 * @author by ls
 * @date 2025/9/15
 * <p>
 * 966. 元音拼写检查器<p>
 * <p>
 * 在给定单词列表 wordlist 的情况下，我们希望实现一个拼写检查器，将查询单词转换为正确的单词。<p>
 * 对于给定的查询单词 query，拼写检查器将会处理两类拼写错误：<p>
 * 大小写：如果查询匹配单词列表中的某个单词（不区分大小写），则返回的正确单词与单词列表中的大小写相同。<p>
 * 例如：wordlist = ["yellow"], query = "YellOw": correct = "yellow"<p>
 * 例如：wordlist = ["Yellow"], query = "yellow": correct = "Yellow"<p>
 * 例如：wordlist = ["yellow"], query = "yellow": correct = "yellow"<p>
 * 元音错误：如果在将查询单词中的元音 ('a', 'e', 'i', 'o', 'u')  分别替换为任何元音后，<p>
 * 能与单词列表中的单词匹配（不区分大小写），则返回的正确单词与单词列表中的匹配项大小写相同。<p>
 * 例如：wordlist = ["YellOw"], query = "yollow": correct = "YellOw"<p>
 * 例如：wordlist = ["YellOw"], query = "yeellow": correct = "" （无匹配项）<p>
 * 例如：wordlist = ["YellOw"], query = "yllw": correct = "" （无匹配项）<p>
 * 此外，拼写检查器还按照以下优先级规则操作：<p>
 * 当查询完全匹配单词列表中的某个单词（区分大小写）时，应返回相同的单词。<p>
 * 当查询匹配到大小写问题的单词时，您应该返回单词列表中的第一个这样的匹配项。<p>
 * 当查询匹配到元音错误的单词时，您应该返回单词列表中的第一个这样的匹配项。<p>
 * 如果该查询在单词列表中没有匹配项，则应返回空字符串。<p>
 * 给出一些查询 queries，返回一个单词列表 answer，其中 answer[i] 是由查询 query = queries[i] 得到的正确单词。<p>
 * <p>
 * 示例 1：<p>
 * 输入：wordlist = ["KiTe","kite","hare","Hare"],<p>
 * queries = ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"]<p>
 * 输出：["kite","KiTe","KiTe","Hare","hare","","","KiTe","","KiTe"]<p>
 * <p>
 * 示例 2:<p>
 * 输入：wordlist = ["yellow"], queries = ["YellOw"]<p>
 * 输出：["yellow"]<p>
 * <p>
 * 提示：<p>
 * 1 <= wordlist.length, queries.length <= 5000<p>
 * 1 <= wordlist[i].length, queries[i].length <= 7<p>
 * wordlist[i] 和 queries[i] 只包含英文字母<p>
 */
public class LeetCode0966 {

    @Test
    public void test() {
//        String[] wordlist = {"KiTe", "kite", "hare", "Hare"}, queries = {"kite", "Kite", "KiTe", "Hare", "HARE", "Hear", "hear", "keti", "keet", "keto"};
//        String[] wordlist = {"yellow"}, queries = {"YellOw"};
        String[] wordlist = {"YellOw"}, queries = {"yollow"};
        System.out.println(Arrays.toString(new Solution().spellchecker(wordlist, queries)));
    }
}

class Solution {

    // 通过缓存字符元音判断减少重复检查
    private static final Set<Character> VOWELS = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));

    public String[] spellchecker(String[] wordlist, String[] queries) {
        // 首先判断是否存在完全匹配的，如果存在，直接返回
        // 然后判断是否存在全部转化为大写/小写之后一致的，如果存在，直接返回
        // 没有找到匹配的单次 -> 是否存在元音错误的单词，如果存在，返回匹配到的第一个，否则，返回空字符串
        int queriesLength = queries.length;
        String[] ans = new String[queriesLength];

        // 使用 List 和 Map 优化查找，保持顺序
        List<String> wordList = Arrays.asList(wordlist);
        // 存储完全匹配的单词
        Set<String> exactMatchSet = new HashSet<>(wordList);
        // 存储小写匹配的单词
        List<String> caseInsensitiveList = new ArrayList<>();
        // 存储元音错误匹配的单词
        List<String> vowelErrorList = new ArrayList<>();

        // 处理 wordlist，按顺序缓存结果
        for (String word : wordList) {
            // 小写匹配
            String lowerWord = word.toLowerCase();
            caseInsensitiveList.add(lowerWord);
            // 处理元音错误
            vowelErrorList.add(getVowelErrorKey(lowerWord));
        }

        for (int i = 0; i < queriesLength; i++) {
            String query = queries[i];

            // 完全匹配
            if (exactMatchSet.contains(query)) {
                ans[i] = query;
                continue;
            }

            // 大小写匹配
            String lowerQuery = query.toLowerCase();
            if (caseInsensitiveList.contains(lowerQuery)) {
                for (int j = 0; j < caseInsensitiveList.size(); j++) {
                    if (lowerQuery.equals(caseInsensitiveList.get(j))) {
                        ans[i] = wordlist[j];
                        break;
                    }
                }
                continue;
            }

            // 元音错误匹配
            String vowelKey = getVowelErrorKey(query).toLowerCase();
            if (vowelErrorList.contains(vowelKey)) {
                for (int j = 0; j < vowelErrorList.size(); j++) {
                    if (vowelKey.equalsIgnoreCase(vowelErrorList.get(j))) {
                        ans[i] = wordlist[j];
                        break;
                    }
                }
                continue;
            }

            // 没有匹配项，返回空字符串
            ans[i] = "";
        }
        return ans;
    }

    // 获取元音错误的标准形式
    private String getVowelErrorKey(String word) {
        StringBuilder sb = new StringBuilder();
        for (char c : word.toCharArray()) {
            if (isVowel(c)) {
                // 用 '#' 表示元音
                sb.append('#');
            } else {
                // 其他字符保持原样
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 判断字符是否是元音
     *
     * @param ch 要判断的字符
     * @return boolean  是否是元音
     */
    public boolean isVowel(char ch) {
        return VOWELS.contains(ch);
    }
}

// 超时
//class Solution {
//
//    public String[] spellchecker(String[] wordlist, String[] queries) {
//        // 首先判断是否存在完全匹配的，如果存在，直接返回
//        // 然后判断是否存在全部转化为大写/小写之后一致的，如果存在，直接返回
//        // 没有找到匹配的单次 -> 是否存在元音错误的单词，如果存在，返回匹配到的第一个，否则，返回空字符串
//        int queriesLength = queries.length;
//        String[] ans = new String[queriesLength];
//        Arrays.fill(ans, "");
//        for (int i = 0; i < queriesLength; i++) {
//            boolean flag1 = true, flag2 = true;
//            int x = Integer.MAX_VALUE;
//            int y = Integer.MAX_VALUE;
//            for (int j = 0; j < wordlist.length; j++) {
//                if (wordlist[j].equals(queries[i])) {
//                    // 完全匹配，直接诶返回
//                    ans[i] = queries[i];
//                    flag1 = true;
//                    flag2 = true;
//                    break;
//                } else if (wordlist[j].equalsIgnoreCase(queries[i])) {
//                    // 存在大小写匹配，记录第一个
//                    flag1 = false;
//                    x = Math.min(x, j);
//                } else {
//                    if (queries[i].length() == wordlist[j].length()) {
//                        int length = queries[i].length();
//                        boolean flag3 = true;
//                        for (int k = 0; k < length; k++) {
//                            if (wordlist[j].charAt(k) == queries[i].charAt(k)
//                                    || 32 == Math.abs(wordlist[j].charAt(k) - queries[i].charAt(k))
//                                    || (isVowel(wordlist[j].charAt(k)) && isVowel(queries[i].charAt(k)))
//                            ) {
//                                flag3 = true;
//                            } else {
//                                flag3 = false;
//                                break;
//                            }
//                        }
//                        if (flag3) {
//                            flag2 = false;
//                            y = Math.min(y, j);
//                        }
//                    }
//                }
//            }
//            if (!flag1) {
//                ans[i] = wordlist[x];
//            } else if (!flag2) {
//                // 没有找到匹配的，判断和当前单词是否存在元音匹配
//                ans[i] = wordlist[y];
//            }
//        }
//        return ans;
//    }
//
//    // 使用 switch 判断字符是否为元音字母
//    public boolean isVowel(char ch) {
//        switch (ch) {
//            case 'a':
//            case 'e':
//            case 'i':
//            case 'o':
//            case 'u':
//            case 'A':
//            case 'E':
//            case 'I':
//            case 'O':
//            case 'U':
//                return true;
//            default:
//                return false;
//        }
//    }
//}
